package com.fingard.dsp.bank.directbank.whccb01;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;

import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.net.*;
import com.fingard.xml.XmlReadMode;
import com.fingard.xml.XmlTextReader;

import java.util.Date;
import java.util.Map;

/**
 * Created by F on 2017/7/10.
 */
public class WHCCB01Base extends DirectBase implements ITcpClient {
    public static void main(String[] args) throws Exception {
        send("20170727091356817UR006500000000000000otherAccQry00002468<?xml version=\"1.0\" encoding=\"GBK\"?><BankData><Sign><SignedData>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</SignedData><PubKey></PubKey></Sign><opReq><opname>otherAccQry</opname><cstNo>100000002246</cstNo><userNo>102338</userNo><serialNo>20170727091356817UR0065</serialNo><userId>UR</userId><reqTime>20170727091356</reqTime><ReqParam><orderFlowNo>20170727091356817UR0065</orderFlowNo></ReqParam></opReq></BankData>");
    }

    String busDateTime14;


    public static void send(String msg) throws Exception {
        WebRequest webRequest = new WebRequest("http://127.0.0.1:7099/yqbank/APIReqServlet");
        //webRequest.setConnectTimeout(1000);
        String[] result = webRequest.upload(msg.getBytes("gbk"), "gbk");
        System.out.println(StringUtils.repeat("=", 20));
        System.out.println("Send msg:\n" + msg.replace(">", ">\n").replace("</", "\n</"));
        System.out.println(StringUtils.repeat("=", 20));
        System.out.println("Receive msg:\n" + result[1].replace(">", ">\n").replace("</", "\n</"));
        System.out.println(StringUtils.repeat("=", 20));
    }

    protected static String getPrefix() {
        return "";
    }

    /**
     * 将请求报文发送给银行
     *
     * @param params 请求报文参数,opReq中的数据报文
     * @return 响应信息，下标为0存储连接信息，1存储返回报文
     * @throws Exception if 连接失败或请求超时
     */
    protected String[] sendToBank(Map<String, String> params, ReqRespHeader reqRespHeader, String opname) throws Exception {
        String ReqParam = "";
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> pair : params.entrySet()) {
            sb.append(String.format("<%1$s>%2$s</%1$s>", pair.getKey(), pair.getValue()));
        }
        ReqParam = sb.toString();
        String opReq = "";
        String headerPart1 = generateHeaderPart1(reqRespHeader);
        String date = headerPart1.substring(0, "yyyyMMddHHmmss".length());
        opReq = String.format("<opReq><opname>%1$s</opname>" +
                        "<cstNo>%2$s</cstNo>" +
                        "<userNo>%3$s</userNo>" +
                        "<serialNo>%4$s</serialNo>" +
                        "<userId>%5$s</userId>" +
                        "<reqTime>%6$s</reqTime>" +
                        "<ReqParam>%7$s</ReqParam></opReq>",
                opname, bankFront.org, bankFront.operator, headerPart1, bankFront.loginName,
                date, ReqParam);


        //先进行签名
        String[] signDatas = new String[]{"", ""};
        String signXml = String.format("<?xml version=\"1.0\" encoding=\"gb2312\"?>" +
                "<msg>" +
                "<msg_head>" +
                "<msg_type>0</msg_type>" +
                "<msg_id>1005</msg_id>" +
                "<msg_sn>0</msg_sn>" +
                "<version>1</version>" +
                "</msg_head>" +
                "<msg_body>" +
                "<origin_data_len>%d</origin_data_len>" +
                "<origin_data>%s</origin_data>" +
                "</msg_body>" +
                "</msg>", opReq.getBytes("GB2312").length, opReq);
        WriteBankLogStep2("发送签名的报文 - " + signXml);

        TcpPortClient tmpClient = new TcpPortClient(bankFront.signURL, Integer.parseInt(bankFront.signPort), this);
        TcpReceiver tmpReceiver = tmpClient.sendMessage(signXml.getBytes("GB2312"));
        signDatas[0] = tmpReceiver.connState;
        if (signDatas[0].length() > 0) {
            return signDatas;
        }
        if (tmpReceiver.recBytes != null) {
            signDatas[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, "GB2312");
        } else {
            signDatas[1] = tmpReceiver.getConnMsg();
        }
        WriteBankLogLn("发送签名的报文 - " + signXml);
        StringBuilder tmpSbMsg = new StringBuilder();
        XmlTextReader tmpBkReader = loadBankRespXmlReader(signDatas[1], tmpSbMsg);
        WriteBankLogLn("收到签名数据 - " + signDatas[1]);


        //签名后的数据
        String[] result = new String[]{"", ""};
        if (signDatas[1].indexOf("<msg>") == -1) {
            result[0] = ConnState.FAIL;
            result[1] = "签名失败，错误代码为" + tmpBkReader.getFirstText("/msg_body/error_no");
            return result;
        }
        String SignedData = tmpBkReader.getFirstText("/msg/msg_body/signed_data").replace("\r", "").replace("\n", "");
        String xml = String.format("<?xml version=\"1.0\" encoding=\"GBK\"?><BankData><Sign>" +
                "<SignedData>%s</SignedData><PubKey></PubKey>" +
                "</Sign>%s</BankData>", SignedData, opReq);
        //添加报文头
        String header = String.format("%s%s%08d",
                headerPart1, StringUtils.repeat("0", 25 - opname.length()) + opname, xml.length()
        );
        xml = header + xml;

        //发送银行前置
        WriteBankLogStep2(xml);
        WebRequest webRequest = new WebRequest(bankFront.serverURL);
        //webRequest.setConnectTimeout(1000);
        result = webRequest.upload(xml.getBytes(getCharset()), getCharset());
        WriteBankLogStep3(result[1]);
        //移除报文头部
        result[1] = result[1].substring(56);
        return result;
    }

    /**
     * 判断响应状态(全0表示成功，否则是失败)
     *
     * @param respcode 响应码
     * @return true表示成功，false失败
     */
    protected boolean success(String respcode) {
        for (int i = 0, bound = respcode.length(); i < bound; i++) {
            if (respcode.charAt(i) != '0') {
                return false;
            }
        }
        return true;
    }

    protected String getRespCode(XmlTextReader reader) throws Exception {
        reader.resetReadMode(XmlReadMode.JustInnerText);
        return reader.getFirstText("/BankData/opRep/hostReturnCode");
    }

    protected String getErrorMsg(XmlTextReader reader) throws Exception {
        reader.resetReadMode(XmlReadMode.JustInnerText);
        return reader.getFirstText("/BankData/opRep/hostErrorMessage");
    }

    protected String getCharset() {
        return getBankConfig().getCharset("GB2312");
    }

    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {
//        if (p_receiver.contentLength == -1) {
//            p_receiver.contentLength = p_receiver.readedLength;
//            p_receiver.contentStartIndex = 0;
//        }
    }

    protected String generateHeaderPart1(ReqRespHeader reqRespHeader) {
        if (StringUtils.isEmpty(reqRespHeader.payDateTime)) {
            reqRespHeader.payDateTime = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
        }
        String headerPart1 = String.format("%s%s%s%s",
                getCommonReqDate(reqRespHeader), "817", bankFront.loginName, getLength4SeqId(reqRespHeader)
        );
        return headerPart1;
    }

    /**
     * 返回长度为4的序列号
     *
     * @param reqRespHeader 请求头
     * @return 长度为4的序列号
     */
    protected String getLength4SeqId(ReqRespHeader reqRespHeader) {
        String seqId = reqRespHeader.reqSeqID;
        if (seqId == null) {
            seqId = reqRespHeader.transSeqID;
        }
        if (seqId.length() < 4) {
            return StringUtils.repeat("0", 4 - seqId.length()) + seqId;
        }
        return seqId.substring(seqId.length() - 4);
    }

    protected String getCommonReqDate(ReqRespHeader reqRespHeader) {
        if (busDateTime14 == null) {
            Date busDate = reqRespHeader.getBusTime(new Date());
            busDateTime14 = DateFormatUtils.format(busDate, "yyyyMMddHHmmss");
        }
        return busDateTime14;
    }
}
